home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr49
/
pcl4c35.zip
/
TERM.C
< prev
next >
Wrap
Text File
|
1993-05-16
|
13KB
|
436 lines
/*
** --- term.c ---
**
** EXAMPLE CODE: Terminal emulator. Can transfer files using
** ASCII, XMODEM, YMODEM, and YMODEM-G protocols.
**
** See TERM.H for configuration parameters.
**
** Link with TERM_IO, MODEM_IO, DIR_IO, CRC, DOS, AMODEM, XYMODEM,
** and XYPACKET. See TERM makefiles.
**
** Do NOT select YMODEM-G when using a null modem cable unless you are
** certain that RTS & CTS are reversed ( this is usually not true ).
**
** This example program (not the PCL4C library) is donated to
** the Public Domain by MarshallSoft Computing, Inc. It is
** provided as an example of the use of the PCL4C.
**
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include "pcl4c.h"
#include "ascii.h"
#include "term.h"
#include "dir_io.h"
#define FALSE 0
#define TRUE !FALSE
#define NORMAL 0x07
#define INVERSE 0x70
#define MESSAGE_POS 48
void MyCrtWrite();
void MyStart();
void ProcessESC();
void ShowProtocol();
void ShowMessage();
void MyExit();
void SayFilename();
void ErrorCheck();
int RxAscii(int,char[],char[],int,int,int,int,int,int);
int TxAscii(int,char[],char[],int,int,int,int,int);
int RxyModem(int,char[],char[],int,int);
int TxyModem(int,char[],char[],int,int);
/*** Global variables ***/
#define SIO_BUFFER_SIZE 2048
int Port; /* current COM port [0..3] */
char FileSpec[15]; /* file name specification */
char Filename[15]; /* file name buffer */
char Buffer[1024]; /* block buffer */
char RxBuf[SIO_BUFFER_SIZE]; /* receive buffer */
char *BaudRate[10] = {"300","600","1200","2400","4800","9600",
"19200","38400","57600","115200"};
int BaudCode; /* baud rate code ( index into BaudRate[] ) */
char *ModelText[4] = {"Small","Compact","Medium","Large"};
char NCGchar = NAK;
int OneKflag = FALSE;
int BatchFlag = FALSE;
char Protocol = 'X';
char TermChar = 0x00;
int CharPace = 0;
int Timeout = 10;
int EchoFlag = TRUE;
/*** main program ***/
main(argc,argv)
int argc;
char *argv[];
{int DataFlag = FALSE;
char c;
int i, k;
int n, rc;
int Delta; /* delta port status */
int Status; /* port status */
char Version;
char temp[81];
/* right number of parameters ? */
if(argc!=3)
{printf("Usage: 'TERM port baud' -- example 'TERM 1 9600'\n");
exit(1);
}
/* get port number from command line */
Port = atoi(argv[1]) - 1;
if((Port<0) || (Port>11))
{printf("Port must be 1 to 12\n");
exit(1);
}
/* get baud rate from command line */
BaudCode = BaudMatch(argv[2]);
if(BaudCode<0)
{printf("Cannot recognize baud rate = %s\n",argv[2]);
exit(1);
}
#if 0
/*** Custom Configuration ***/
SioIRQ(COM1,IRQ4,FirstISR);
SioIRQ(COM2,IRQ3,SecondISR);
/* use IRQ2 for COM3 */
SioIRQ(COM3,IRQ2,ThirdISR);
/* use IRQ5 for COM4 */
SioIRQ(COM4,IRQ5,FourthISR);
#endif
/* setup receive buffer */
ErrorCheck( SioRxBuf(Port,RxBuf,Size2K) );
/* set parms & reset (initialize) COM port */
ErrorCheck( SioParms(Port,NoParity,OneStopBit,WordLength8) );
MyStart(Port,BaudCode);
/* set DTR and RTS */
SioDTR(Port,'S');
SioRTS(Port,'S');
/* init CRC table */
InitCRC();
/* initialize screen */
Scroll(0,0,24,79,0,NORMAL);
/* display status message */
sprintf(temp," COM%d %s %c 'ESC for menu' ",1+Port,BaudRate[BaudCode],Protocol);
ShowMessage(0,temp);
Position(1,0);
/* display some info */
puts("TERM 5/1/93");
Version = SioInfo('V');
printf("Library = %d.%d\n",Version/16,Version%16);
printf("Memory Model = %s\n",ModelText[3&SioInfo('M')] );
#if RTS_CTS_CONTROL
SioFlow(Port,7*ONE_SECOND);
printf("Flow Control enabled. CTS = ");
if(SioCTS(Port)) puts("ON");
else puts("OFF");
#endif
/* Set FIFO level */
if( SioFIFO(Port,LEVEL_14) ) puts("INS16550 detected");
/* clear PCL4C receive buffer */
ErrorCheck( SioRxFlush(Port) );
/* see TERM.H for definition of AT_COMMAND_SET */
#if AT_COMMAND_SET
/* wait for Modem to say its ready */
printf("Waiting for Modem DSR.");
while( !SioDSR(Port) )
{
if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
putchar('.');
SioDelay(18);
}
putchar('\n');
/* initialize (Hayes compatible) modem */
SendTo(Port,"!AT!!~");
SendTo(Port,"!AT E1 S7=60 S11=60 V1 X1 Q0 S0=1!");
if(WaitFor(Port,"OK")) printf("\nMODEM READY\n");
else printf("\nWARNING: Expected OK not received\n");
#endif
/* enter terminal loop */
SioRxFlush(Port);
while(1)
{/* Control-BREAK ? */
if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
/* was key pressed ? */
if(SioKeyPress())
{/* read key press */
i = SioKeyRead();
if((char)i==ESC)
{/* process user's request */
ProcessESC();
ShowMessage(strlen(BaudRate[BaudCode])+9,"'ESC for Menu' ");
continue;
}
else PutChar(Port,i);
}
/* was break detected ? */
if( SioBrkSig(Port,'D') ) DisplayLine("BREAK detected ",NULL,0);
/* any incoming over serial port ? */
i = GetChar(Port,0);
if(i>-1)
{/* good character */
if(DataFlag&((i<0x20)||(i>0x7e)))
{MyCrtWrite('^');
MyCrtWrite('@'+i);
}
else MyCrtWrite(i);
}
/* any change in DCD or DSR ? */
Delta = SioModem(Port,DeltaDCD|DeltaDSR);
if(Delta)
{/* display new status */
Status = SioModem(Port,(char)(DCD|DSR));
if(!Status&DeltaDCD) MyExit(0,"Dropped DSD");
if(!Status&DeltaDSR) MyExit(0,"Dropped DSR");
}
} /* end -- key pressed */
}
/*** write to screen except for bottom line ***/
void MyCrtWrite(ch)
char ch;
{/* write character */
SioCrtWrite(ch);
/* scroll all but bottom line */
if(GetRow()==24)
{Scroll(0,0,23,79,1,NORMAL);
Position(23,0);
}
}
/*** make multiple attempts to reset port ***/
void MyStart(Port,BaudCode)
int Port;
int BaudCode;
{int i, rc;
/* try up to 3 times to reset COM port */
for(i=0;i<3;i++)
{printf("Resetting COM%d at %s baud\n",Port+1,BaudRate[BaudCode]);
if( (rc = SioReset(Port,BaudCode))==0) return;
if(rc<0) MyExit(rc,"Error resetting port");
SioDone(Port);
/* display errors */
if(rc&OverrunError) puts("Overrun Error");
if(rc&ParityError) puts("Parity Error");
if(rc&FramingError) puts("Framing Error");
if(rc&BreakDetect) puts("Break Detect");
}
exit(1);
}
/*** find baud rate string in table ***/
int BaudMatch(ptr)
char *ptr;
{int i;
/* find baud rate in table */
for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
return(-1);
}
/*** user pressed Escape */
void ProcessESC()
{int i;
int rc;
int c1, c2;
char Answer[2]; /* array for 1 char answer */
int row, col;
/* user pressed <ESC> */
Answer[0] = '?';
Answer[1] = '\0';
DisplayLine("Q)uit P)rotocol S)end R)eceive: ",Answer,1);
if(strlen(Answer)) switch(toupper(Answer[0]))
{
case 'P':
#if RTS_CTS_CONTROL
DisplayLine("A)scii X)modem Y)modem ymodem-G): ",Answer,1);
#else
DisplayLine("A)scii X)modem Y)modem: ",Answer,1);
#endif
if(strlen(Answer)) switch( toupper(Answer[0]) )
{
case 'A':
Protocol = 'A';
ShowProtocol();
TermChar = 0x18; /* CAN or control-X */
CharPace = 0; /* no inter-byte delay */
Timeout = 7; /* timeout after 7 seconds */
EchoFlag = TRUE; /* do local echo */
DisplayLine("Protocol = ASCII",NULL,1);
break;
case 'X':
Protocol = 'X';
ShowProtocol();
OneKflag = FALSE;
BatchFlag = FALSE;
NCGchar = NAK;
DisplayLine("Protocol = XMODEM",NULL,1);
break;
case 'Y':
Protocol = 'Y';
ShowProtocol();
OneKflag = TRUE;
BatchFlag = TRUE;
NCGchar = 'C';
DisplayLine("Protocol = YMODEM",NULL,1);
break;
#if RTS_CTS_CONTROL
case 'G':
Protocol = 'G';
ShowProtocol();
OneKflag = TRUE;
BatchFlag = TRUE;
NCGchar = 'G';
DisplayLine("Protocol = YMODEM-G",NULL,1);
break;
#endif
default:
DisplayLine("Must answer X, Y, or G",NULL,1);
break;
}
break;
case 'Q':
MyExit(0,"User pressed ESC");
break;
case 'R':
ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
if(Protocol=='A')
{/* Ascii */
DisplayLine("Enter filename:",Filename,15);
if(strlen(Filename)==0) break;
RxAscii(Port,Filename,Buffer,1024,SIO_BUFFER_SIZE,FALSE,TermChar,Timeout,EchoFlag);
break;
}
/* XMODEM / YMODEM receive */
if(BatchFlag)
{do
{/* receive files till get empty filename */
RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
if(SioKeyPress()) break;
} while(Filename[0]!='\0');
}
else /* not Batch */
{DisplayLine("Enter filename:",Filename,15);
if(strlen(Filename)==0) break;
RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
}
break;
case 'S':
ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
DisplayLine("Enter filename:",FileSpec,15);
if(strlen(FileSpec)==0) break;
if(Protocol=='A')
{/* Ascii */
TxAscii(Port,FileSpec,Buffer,1024,FALSE,CharPace,TermChar,EchoFlag);
break;
}
if(BatchFlag)
{/* YMODEM send */
if(FindFirst(FileSpec,Filename))
{SayFilename(Filename);
TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
while(FindNext(Filename))
{SioDelay(4);
SayFilename(Filename);
TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
}
/* send empty filename */
Filename[0] = '\0';
SioDelay(5);
TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
}
}
else
{/* XMODEM send */
TxyModem(Port,FileSpec,Buffer,OneKflag,BatchFlag);
}
break;
default:
DisplayLine("Must answer Q, P, S, or R",NULL,0);
break;
} /* end switch */
}
/*** show protocol choosen ***/
void ShowProtocol()
{int SaveRow;
int SaveCol;
SaveRow = GetRow();
SaveCol = GetCol();
Position(24,MESSAGE_POS+strlen(BaudRate[BaudCode])+7);
AttrWrite(Protocol,INVERSE);
Position(SaveRow,SaveCol);
}
/*** show chosen message ***/
void ShowMessage(Pos,Msg)
int Pos;
char *Msg;
{int i;
int SaveRow;
int SaveCol;
int Col;
SaveRow = GetRow();
SaveCol = GetCol();
Col = MESSAGE_POS+Pos;
for(i=0;i<strlen(Msg);i++)
{Position(24,Col++);
AttrWrite(Msg[i],INVERSE);
}
Position(SaveRow,SaveCol);
}
/*** exit program ***/
void MyExit(code,msg)
int code;
char *msg;
{int rc;
if(code<0) SioError(code);
/* Assert UART break & sign off */
SioBrkSig(Port,'A');
printf("\nTERMINATING: %s\n",msg);
SioDelay(ONE_SECOND/2);
SioDone(Port);
exit(0);
}
/*** display file name in status area ***/
void SayFilename(Text)
char *Text;
{char Temp[40];
strcpy(Temp,"Sending ");
strcat(Temp,Text);
DisplayLine(Temp,NULL,0);
SioDelay(ONE_SECOND/2);
}
/*** check for error ***/
void ErrorCheck(Code)
int Code;
{/* trap PCL error codes */
if(Code<0)
{SioError(Code);
SioDone(Port);
exit(1);
}
} /* end ErrorCheck */